#include <pcap/pcap.h>
#include "pcap.h"
#include "options.h"
#include "ieee.h"

#define SNAPLEN (65536)
#define TIMEOUT (100)
static pcap_t *_pcap;

void engine_pcap_handle(unsigned char *args, const struct pcap_pkthdr *pkh, const unsigned char *data)
{
    //static unsigned long long cnt = 0;
    //struct sk_buff skb;
    //skb.data = (char *)data;
    //skb.len = pkh->caplen;
    //skb.type = NONE;
    //printf("%d\r", ++cnt);
    handle_ieee_802_3x(data);
    fflush(stdout);
}

int engine_pcap_init_device(void)
{
    int status;
    char errbuf[PCAP_ERRBUF_SIZE];
    _pcap = pcap_create(options.ifname, errbuf);
    if(!_pcap){
        fprintf(stderr, "error: %s\n",errbuf);
        return -1;
    }
    status = pcap_set_snaplen(_pcap, SNAPLEN);
    if(status != 0) {
        fprintf(stderr, "error: %s\n",pcap_geterr(_pcap));
        return -1;
    }
    status = pcap_set_promisc(_pcap, 1); 
    if (status != 0 && status != PCAP_ERROR_ACTIVATED) {
        fprintf(stderr, "error: %s\n",pcap_geterr(_pcap));
        return -1; 
    }
    status = pcap_set_timeout(_pcap, TIMEOUT);
    if(status != 0) {
        fprintf(stderr, "error: %s\n",pcap_geterr(_pcap));
        return -1;
    }
    return 0;
}

int engine_pcap_init_file(void)
{
    int status;
    char errbuf[PCAP_ERRBUF_SIZE];
    _pcap = pcap_open_offline(options.ifname, errbuf);
    if(!_pcap){
        fprintf(stderr, "error: %s\n",errbuf);
        return -1;
    }
    return 0;
}

int engine_pcap_init(void)
{
    if(!options.ifname) {
        fprintf(stderr, "ifname can not be NULL.\n");
        return -1;
    }
    if(options.is_file) {
        return engine_pcap_init_file();
    } else {
        return engine_pcap_init_device();
    }
}

int engine_pcap_loop_device(void)
{
    int status;
    status = pcap_activate(_pcap);
    if(status != 0) {
        fprintf(stderr, "error: %s\n",pcap_geterr(_pcap));
        return -1;
    }
    status = pcap_loop(_pcap, -1, engine_pcap_handle, NULL);
    if(status != 0) {
        fprintf(stderr, "error: %s\n",pcap_geterr(_pcap));
        return -1;
    }
    return 0;
}

int engine_pcap_loop_file(void)
{
    int status;
    status = pcap_loop(_pcap, -1, engine_pcap_handle, NULL);
    if(status != 0) {
        fprintf(stderr, "error: %s\n",pcap_geterr(_pcap));
        return -1;
    }
    return 0;
}

int engine_pcap_loop(void)
{
    if(options.is_file) {
        return engine_pcap_loop_file();
    } else {
        return engine_pcap_loop_device();
    }
}

int engine_pcap_destory(void)
{
    pcap_close(_pcap);
    return 0;
}
